<?php
/**
 *------------------------------------------------
 * Author YYT[QQ:375776626]
 *------------------------------------------------
 */

class PHP_RPC
{
    public static function server($object)
    {
        return new PHP_RPC_SERVER($object);
    }
    public static function client($url)
    {
        return PHP_RPC_CLIENT::connect($url);
    }
}
class PHP_RPC_SERVER
{
    private $_object;
    public function __construct($object)
    {
        $this->_object = $object;
    }
    private static function _request()
    {
        if ($_SERVER['REQUEST_METHOD'] == 'POST' && !empty($_SERVER['CONTENT_TYPE']) && $_SERVER['CONTENT_TYPE'] == 'application/PHP_RPC') {
            return true;
        }
        return false;
    }
    public function handle()
    {
        if (!self::_request()) return;
        $request = unserialize(file_get_contents('php://input'));
        if ($result = @call_user_func_array(array($this->_object, $request['method']), $request['args'])) {
            exit(serialize($result));
        }
    }
    public function display()
    {
        if (self::_request()) return;
        if (is_string($this->_object) && !class_exists($this->_object)) return;
        $Class = new ReflectionClass($this->_object);

        $view = '<!DOCTYPE html><head><title>'.get_class($this->_object).'帮助</title>';
        $view .= '<style type="text/css">body,h1{ margin:0; padding:0; } body{ background:#80ff80 }</style>';
        $view .= '</head><body>';
        $view .= '<h1 style="background:#9999cc;border-bottom:5px #666699 solid">'.get_class($this->_object).'帮助</h1>';
        $methodObjects = $Class->getMethods(ReflectionProperty::IS_PUBLIC);
        array_multisort($methodObjects);
        $view .='<div style="margin:20px;border:1px #666 solid; background:#a6fda6;padding:5px;">索引 ';
        foreach ($methodObjects as $methodObject) {
            $view .= '<p><a href="#'.$methodObject->name.'" style="color:blue">'.$methodObject->name.'</a></p>';
        }
        $view .='</div>';
        foreach ($methodObjects as $methodObject) {
            $view .= '<div id="'.$methodObject->name.'" style="margin:20px;border:1px #666 solid; background:#a6fda6">';
            $doc = $methodObject->getDocComment();
            if ($doc) $view .= '<pre style="color:green">&nbsp;&nbsp;&nbsp;&nbsp;'.$methodObject->getDocComment().'</pre>';
            $view .= '<h2>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#800000">'.$methodObject->class.'</span>';
            $view .= '::<span style="color:blue">'.$methodObject->name.'</span>(';
            foreach ($methodObject->getParameters() as $parameter) {
                $view .= '<span style="color:blue">$</span><span style="color:#008080">'.$parameter->name.'</span>';
                if ($parameter->isOptional()) {
                    $view .= ' = <span style="color:#ff00ff">\''.$parameter->getDefaultValue().'\'</span>';
                }
                $view .= ', ';
            }
            $view = rtrim($view, ', ');
            $view .= ')</h2>';
            $view .= '</div>';
        }
        $view .= '</body></html>';
        echo $view;
    }
}
class PHP_RPC_CLIENT
{
    private static $_url;
    private static $_timeout;
    public static function connect($url, $timeout = 5)
    {
        self::$_url = $url;
        self::$_timeout = $timeout;
        return new self();
    }
    public function __call($method, $args)
    {
        if (!self::_checkUrlIsOk(self::$_url)) return;
        $request = array('method' => $method, 'args' => $args);
        $options = array(
            'http' => array(
                'method'  => 'POST',
                'header'  => 'Content-type: application/PHP_RPC',
                'content' => serialize($request)
            )
        );
        $context = stream_context_create($options);
        if ($fp = @fopen(self::$_url, 'r', false, $context)) {
            $result = '';
            while ($row = fgets($fp)) $result .= trim($row)."\n";
            return @unserialize($result);
        }
    }
    private static function _checkUrlIsOk($url)
    {
        $curl = curl_init($url);
        //不取回数据
        curl_setopt($curl, CURLOPT_NOBODY, true);
        curl_setopt($curl, CURLOPT_TIMEOUT, self::$_timeout);
        $result = curl_exec($curl);
        //如果请求没有发送失败
        if ($result !== false) {
            //再检查http响应码()
            $statusCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
            if ($statusCode != 404) return true;
        }
        curl_close($curl);
        return false;
    }
}


/*
demo
============server============
class Api
{
    public function show($string)
    {
        return $string;
    }
}

$Server = PHP_RPC::server(new Api());
$Server->handle();
if (isset($_GET['help'])) {
    $Server->display();
}

============client============

$Client = PHP_RPC::client('http://localhost/temp/rpc/server.php');
echo $Client->show('Hello World!');

*/